
<!doctype html>
<html lang="zh" class="no-js">
  <head>
    
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width,initial-scale=1">
      
        <meta name="description" content="脚本文档">
      
      
        <meta name="author" content="Logan">
      
      
        <link rel="canonical" href="http://localhost:8000/shell/scripts/">
      
      
        <link rel="prev" href="../text_processing/">
      
      
      
      <link rel="icon" href="../../image/favicon.ico">
      <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.5.50">
    
    
      
        <title>Shell脚本实战 - 运维无忧文档</title>
      
    
    
      <link rel="stylesheet" href="../../assets/stylesheets/main.a40c8224.min.css">
      
        
        <link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
      
      


    
    
      
    
    
      
        
        
        <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
        <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
      
    
    
      <link rel="stylesheet" href="../../css/extra.css">
    
      <link rel="stylesheet" href="../../css/prism.css">
    
    <script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
    
      

    
    
    
  </head>
  
  
    
    
      
    
    
    
    
    <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="blue">
  
    
    <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
    <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
    <label class="md-overlay" for="__drawer"></label>
    <div data-md-component="skip">
      
        
        <a href="#shell" class="md-skip">
          跳转至
        </a>
      
    </div>
    <div data-md-component="announce">
      
    </div>
    
    
      

  

<header class="md-header md-header--shadow" data-md-component="header">
  <nav class="md-header__inner md-grid" aria-label="页眉">
    <a href="../.." title="运维无忧文档" class="md-header__button md-logo" aria-label="运维无忧文档" data-md-component="logo">
      
  <img src="../../image/logo.png" alt="logo">

    </a>
    <label class="md-header__button md-icon" for="__drawer">
      
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
    </label>
    <div class="md-header__title" data-md-component="header-title">
      <div class="md-header__ellipsis">
        <div class="md-header__topic">
          <span class="md-ellipsis">
            运维无忧文档
          </span>
        </div>
        <div class="md-header__topic" data-md-component="header-topic">
          <span class="md-ellipsis">
            
              Shell脚本实战
            
          </span>
        </div>
      </div>
    </div>
    
      
        <form class="md-header__option" data-md-component="palette">
  
    
    
    
    <input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="blue"  aria-label="Switch to dark mode"  type="radio" name="__palette" id="__palette_0">
    
      <label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"/></svg>
      </label>
    
  
    
    
    
    <input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="blue"  aria-label="Switch to light mode"  type="radio" name="__palette" id="__palette_1">
    
      <label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"/></svg>
      </label>
    
  
</form>
      
    
    
      <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
    
    
    
      <label class="md-header__button md-icon" for="__search">
        
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
      </label>
      <div class="md-search" data-md-component="search" role="dialog">
  <label class="md-search__overlay" for="__search"></label>
  <div class="md-search__inner" role="search">
    <form class="md-search__form" name="search">
      <input type="text" class="md-search__input" name="query" aria-label="搜索" placeholder="搜索" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
      <label class="md-search__icon md-icon" for="__search">
        
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
        
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
      </label>
      <nav class="md-search__options" aria-label="查找">
        
        <button type="reset" class="md-search__icon md-icon" title="清空当前内容" aria-label="清空当前内容" tabindex="-1">
          
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
        </button>
      </nav>
      
    </form>
    <div class="md-search__output">
      <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
        <div class="md-search-result" data-md-component="search-result">
          <div class="md-search-result__meta">
            正在初始化搜索引擎
          </div>
          <ol class="md-search-result__list" role="presentation"></ol>
        </div>
      </div>
    </div>
  </div>
</div>
    
    
      <div class="md-header__source">
        <a href="https://git.opsx.vip/docs/wuyou.run.git" title="前往仓库" class="md-source" data-md-component="source">
  <div class="md-source__icon md-icon">
    
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81"/></svg>
  </div>
  <div class="md-source__repository">
    wuyou.run
  </div>
</a>
      </div>
    
  </nav>
  
</header>
    
    <div class="md-container" data-md-component="container">
      
      
        
          
        
      
      <main class="md-main" data-md-component="main">
        <div class="md-main__inner md-grid">
          
            
              
              <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    



<nav class="md-nav md-nav--primary" aria-label="导航栏" data-md-level="0">
  <label class="md-nav__title" for="__drawer">
    <a href="../.." title="运维无忧文档" class="md-nav__button md-logo" aria-label="运维无忧文档" data-md-component="logo">
      
  <img src="../../image/logo.png" alt="logo">

    </a>
    运维无忧文档
  </label>
  
    <div class="md-nav__source">
      <a href="https://git.opsx.vip/docs/wuyou.run.git" title="前往仓库" class="md-source" data-md-component="source">
  <div class="md-source__icon md-icon">
    
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81"/></svg>
  </div>
  <div class="md-source__repository">
    wuyou.run
  </div>
</a>
    </div>
  
  <ul class="md-nav__list" data-md-scrollfix>
    
      
      
  
  
  
  
    <li class="md-nav__item">
      <a href="../.." class="md-nav__link">
        
  
  <span class="md-ellipsis">
    首页
  </span>
  

      </a>
    </li>
  

    
      
      
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
        
          
          <label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    Linux基础设施
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2">
            <span class="md-nav__icon md-icon"></span>
            Linux基础设施
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1" >
        
          
          <label class="md-nav__link" for="__nav_2_1" id="__nav_2_1_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    基础环境配置
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_1_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2_1">
            <span class="md-nav__icon md-icon"></span>
            基础环境配置
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/system_init/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    系统初始化
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/dev_env/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    开发环境搭建
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
        
          
          <label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    常用服务部署
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2_2">
            <span class="md-nav__icon md-icon"></span>
            常用服务部署
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2_1" >
        
          
          <label class="md-nav__link" for="__nav_2_2_1" id="__nav_2_2_1_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    Web服务与代理
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_2_1_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2_2_1">
            <span class="md-nav__icon md-icon"></span>
            Web服务与代理
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/web_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    Web服务
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/proxy_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    代理服务
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/services-loadbalancing/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    负载均衡服务
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/cache_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    缓存加速服务
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2_2" >
        
          
          <label class="md-nav__link" for="__nav_2_2_2" id="__nav_2_2_2_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    数据存储
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_2_2_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2_2_2">
            <span class="md-nav__icon md-icon"></span>
            数据存储
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/database_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    数据库服务
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/storage_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    文件存储服务
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2_3" >
        
          
          <label class="md-nav__link" for="__nav_2_2_3" id="__nav_2_2_3_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    监控与日志
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_2_3_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2_2_3">
            <span class="md-nav__icon md-icon"></span>
            监控与日志
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/monitoring_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    监控系统
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/logging_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    日志管理
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/message_queue_services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    消息队列
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_3" >
        
          
          <label class="md-nav__link" for="__nav_2_3" id="__nav_2_3_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    系统运维
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_3_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_2_3">
            <span class="md-nav__icon md-icon"></span>
            系统运维
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/storage/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    存储与备份
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/lvm/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    LVM存储管理
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/network/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    网络服务配置
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/monitor/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    监控与日志
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

    
      
      
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
        
          
          <label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    容器与编排
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_3">
            <span class="md-nav__icon md-icon"></span>
            容器与编排
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_1" >
        
          
          <label class="md-nav__link" for="__nav_3_1" id="__nav_3_1_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    Docker
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_1_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_3_1">
            <span class="md-nav__icon md-icon"></span>
            Docker
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/docker/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    基础安装
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/docker/build/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    镜像构建
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/docker/services/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    常用服务部署
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/docker/network-storage/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    网络与存储
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/docker-compose/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    Docker Compose
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" >
        
          
          <label class="md-nav__link" for="__nav_3_3" id="__nav_3_3_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    Kubernetes
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_3_3">
            <span class="md-nav__icon md-icon"></span>
            Kubernetes
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/kubernetes/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    集群部署
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/kubernetes/resources/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    资源管理
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/kubernetes/operations/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    运维操作
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/kubernetes/best-practices/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    最佳实践
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

    
      
      
  
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
        
          
          <label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    DevOps工具链
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
          <label class="md-nav__title" for="__nav_4">
            <span class="md-nav__icon md-icon"></span>
            DevOps工具链
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/cicd/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    CI/CD流水线
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../../installation/devops/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    自动化运维
  </span>
  

      </a>
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

    
      
      
  
  
    
  
  
  
    
    
    
    
    <li class="md-nav__item md-nav__item--active md-nav__item--nested">
      
        
        
        <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
        
          
          <label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
            
  
  <span class="md-ellipsis">
    Shell 快速入门
  </span>
  

            <span class="md-nav__icon md-icon"></span>
          </label>
        
        <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
          <label class="md-nav__title" for="__nav_5">
            <span class="md-nav__icon md-icon"></span>
            Shell 快速入门
          </label>
          <ul class="md-nav__list" data-md-scrollfix>
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../introduction/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    Linux 基础命令
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../commands/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    常用命令集
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../variables_and_data_types/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    变量和数据类型
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../control_flow/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    控制流程 (if、else、for、while)
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../functions/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    Shell函数
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
  
  
    <li class="md-nav__item">
      <a href="../text_processing/" class="md-nav__link">
        
  
  <span class="md-ellipsis">
    文本处理三剑客
  </span>
  

      </a>
    </li>
  

              
            
              
                
  
  
    
  
  
  
    <li class="md-nav__item md-nav__item--active">
      
      <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
      
      
        
      
      
        <label class="md-nav__link md-nav__link--active" for="__toc">
          
  
  <span class="md-ellipsis">
    Shell脚本实战
  </span>
  

          <span class="md-nav__icon md-icon"></span>
        </label>
      
      <a href="./" class="md-nav__link md-nav__link--active">
        
  
  <span class="md-ellipsis">
    Shell脚本实战
  </span>
  

      </a>
      
        

<nav class="md-nav md-nav--secondary" aria-label="目录">
  
  
  
    
  
  
    <label class="md-nav__title" for="__toc">
      <span class="md-nav__icon md-icon"></span>
      目录
    </label>
    <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
      
        <li class="md-nav__item">
  <a href="#_1" class="md-nav__link">
    <span class="md-ellipsis">
      基础知识
    </span>
  </a>
  
    <nav class="md-nav" aria-label="基础知识">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_2" class="md-nav__link">
    <span class="md-ellipsis">
      脚本基本结构
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_3" class="md-nav__link">
    <span class="md-ellipsis">
      最佳实践
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_4" class="md-nav__link">
    <span class="md-ellipsis">
      实用脚本示例
    </span>
  </a>
  
    <nav class="md-nav" aria-label="实用脚本示例">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_5" class="md-nav__link">
    <span class="md-ellipsis">
      系统监控脚本
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_6" class="md-nav__link">
    <span class="md-ellipsis">
      备份脚本
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_7" class="md-nav__link">
    <span class="md-ellipsis">
      日志分析脚本
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_8" class="md-nav__link">
    <span class="md-ellipsis">
      实战应用场景
    </span>
  </a>
  
    <nav class="md-nav" aria-label="实战应用场景">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_9" class="md-nav__link">
    <span class="md-ellipsis">
      自动化部署
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_10" class="md-nav__link">
    <span class="md-ellipsis">
      批量用户管理
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_11" class="md-nav__link">
    <span class="md-ellipsis">
      服务健康检查
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_12" class="md-nav__link">
    <span class="md-ellipsis">
      调试与故障排除技巧
    </span>
  </a>
  
    <nav class="md-nav" aria-label="调试与故障排除技巧">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_13" class="md-nav__link">
    <span class="md-ellipsis">
      常用调试技巧
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_14" class="md-nav__link">
    <span class="md-ellipsis">
      常见陷阱与解决方案
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_15" class="md-nav__link">
    <span class="md-ellipsis">
      日志记录最佳实践
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_16" class="md-nav__link">
    <span class="md-ellipsis">
      进阶脚本编程
    </span>
  </a>
  
    <nav class="md-nav" aria-label="进阶脚本编程">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_17" class="md-nav__link">
    <span class="md-ellipsis">
      函数库与模块化
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_18" class="md-nav__link">
    <span class="md-ellipsis">
      信号处理与优雅退出
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_19" class="md-nav__link">
    <span class="md-ellipsis">
      并发处理
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#shell_1" class="md-nav__link">
    <span class="md-ellipsis">
      Shell性能优化技巧
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
    </ul>
  
</nav>
      
    </li>
  

              
            
          </ul>
        </nav>
      
    </li>
  

    
  </ul>
</nav>
                  </div>
                </div>
              </div>
            
            
              
              <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
                <div class="md-sidebar__scrollwrap">
                  <div class="md-sidebar__inner">
                    

<nav class="md-nav md-nav--secondary" aria-label="目录">
  
  
  
    
  
  
    <label class="md-nav__title" for="__toc">
      <span class="md-nav__icon md-icon"></span>
      目录
    </label>
    <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
      
        <li class="md-nav__item">
  <a href="#_1" class="md-nav__link">
    <span class="md-ellipsis">
      基础知识
    </span>
  </a>
  
    <nav class="md-nav" aria-label="基础知识">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_2" class="md-nav__link">
    <span class="md-ellipsis">
      脚本基本结构
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_3" class="md-nav__link">
    <span class="md-ellipsis">
      最佳实践
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_4" class="md-nav__link">
    <span class="md-ellipsis">
      实用脚本示例
    </span>
  </a>
  
    <nav class="md-nav" aria-label="实用脚本示例">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_5" class="md-nav__link">
    <span class="md-ellipsis">
      系统监控脚本
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_6" class="md-nav__link">
    <span class="md-ellipsis">
      备份脚本
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_7" class="md-nav__link">
    <span class="md-ellipsis">
      日志分析脚本
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_8" class="md-nav__link">
    <span class="md-ellipsis">
      实战应用场景
    </span>
  </a>
  
    <nav class="md-nav" aria-label="实战应用场景">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_9" class="md-nav__link">
    <span class="md-ellipsis">
      自动化部署
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_10" class="md-nav__link">
    <span class="md-ellipsis">
      批量用户管理
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_11" class="md-nav__link">
    <span class="md-ellipsis">
      服务健康检查
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_12" class="md-nav__link">
    <span class="md-ellipsis">
      调试与故障排除技巧
    </span>
  </a>
  
    <nav class="md-nav" aria-label="调试与故障排除技巧">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_13" class="md-nav__link">
    <span class="md-ellipsis">
      常用调试技巧
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_14" class="md-nav__link">
    <span class="md-ellipsis">
      常见陷阱与解决方案
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_15" class="md-nav__link">
    <span class="md-ellipsis">
      日志记录最佳实践
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
        <li class="md-nav__item">
  <a href="#_16" class="md-nav__link">
    <span class="md-ellipsis">
      进阶脚本编程
    </span>
  </a>
  
    <nav class="md-nav" aria-label="进阶脚本编程">
      <ul class="md-nav__list">
        
          <li class="md-nav__item">
  <a href="#_17" class="md-nav__link">
    <span class="md-ellipsis">
      函数库与模块化
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_18" class="md-nav__link">
    <span class="md-ellipsis">
      信号处理与优雅退出
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#_19" class="md-nav__link">
    <span class="md-ellipsis">
      并发处理
    </span>
  </a>
  
</li>
        
          <li class="md-nav__item">
  <a href="#shell_1" class="md-nav__link">
    <span class="md-ellipsis">
      Shell性能优化技巧
    </span>
  </a>
  
</li>
        
      </ul>
    </nav>
  
</li>
      
    </ul>
  
</nav>
                  </div>
                </div>
              </div>
            
          
          
            <div class="md-content" data-md-component="content">
              <article class="md-content__inner md-typeset">
                
                  

  
  


<h1 id="shell">Shell脚本实战指南</h1>
<h2 id="_1">基础知识</h2>
<h3 id="_2">脚本基本结构</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# 脚本功能说明：示例脚本基本结构

# [配置] 常量和配置项
LOG_FILE=&quot;/tmp/script.log&quot;
MAX_RETRIES=3

# [函数] 日志记录函数
log() {
    local timestamp=$(date &quot;+%Y-%m-%d %H:%M:%S&quot;)
    echo &quot;[$timestamp] $1&quot; &gt;&gt; &quot;$LOG_FILE&quot;
    echo &quot;[$timestamp] $1&quot;
}

# [函数] 错误处理函数
handle_error() {
    log &quot;错误: $1&quot;
    exit 1
}

# [主逻辑] 主程序开始
log &quot;开始执行脚本&quot;

# 执行某操作
if ! some_command; then
    handle_error &quot;some_command 执行失败&quot;
fi

log &quot;脚本执行完成&quot;
exit 0
</code></pre>
<h3 id="_3">最佳实践</h3>
<ol>
<li><strong>总是在脚本顶部使用解释器</strong>：使用<code>#!/bin/bash</code>或<code>#!/bin/sh</code>指定解释器</li>
<li><strong>添加文件头部注释</strong>：包含作者、脚本功能、使用方法</li>
<li><strong>常量使用大写</strong>：如<code>MAX_COUNT=10</code></li>
<li><strong>添加足够的注释</strong>：特别是对复杂逻辑</li>
<li><strong>使用函数模块化代码</strong>：将重复代码封装为函数</li>
<li><strong>添加错误处理</strong>：检查返回值，处理异常情况</li>
<li><strong>日志记录</strong>：记录关键操作和错误信息</li>
<li><strong>设置退出状态码</strong>：成功返回0，失败返回非0值</li>
</ol>
<h2 id="_4">实用脚本示例</h2>
<h3 id="_5">系统监控脚本</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# [系统监控] CPU、内存和磁盘使用情况监控

# 配置项
OUTPUT_FILE=&quot;/tmp/system_status_$(date +%Y%m%d).log&quot;
THRESHOLD_CPU=80
THRESHOLD_MEM=80
THRESHOLD_DISK=90

# 日志函数
log_status() {
    echo &quot;$(date '+%Y-%m-%d %H:%M:%S') - $1&quot; | tee -a &quot;$OUTPUT_FILE&quot;
}

log_status &quot;========== 系统状态检查开始 ==========&quot;

# CPU使用率检查
CPU_USAGE=$(top -bn1 | grep &quot;Cpu(s)&quot; | awk '{print $2 + $4}')
log_status &quot;CPU使用率: ${CPU_USAGE}%&quot;

if (( $(echo &quot;$CPU_USAGE &gt; $THRESHOLD_CPU&quot; | bc -l) )); then
    log_status &quot;警告: CPU使用率超过${THRESHOLD_CPU}%!&quot;
fi

# 内存使用检查
MEM_INFO=$(free -m | grep Mem)
MEM_TOTAL=$(echo &quot;$MEM_INFO&quot; | awk '{print $2}')
MEM_USED=$(echo &quot;$MEM_INFO&quot; | awk '{print $3}')
MEM_USAGE=$(echo &quot;scale=2; $MEM_USED*100/$MEM_TOTAL&quot; | bc)

log_status &quot;内存使用: ${MEM_USED}MB/${MEM_TOTAL}MB (${MEM_USAGE}%)&quot;

if (( $(echo &quot;$MEM_USAGE &gt; $THRESHOLD_MEM&quot; | bc -l) )); then
    log_status &quot;警告: 内存使用率超过${THRESHOLD_MEM}%!&quot;
fi

# 磁盘使用检查
log_status &quot;磁盘使用情况:&quot;
df -h | grep -vE &quot;tmpfs|cdrom&quot; | tail -n +2 | while read -r line; do
    DISK_USAGE=$(echo &quot;$line&quot; | awk '{print $5}' | sed 's/%//')
    MOUNT_POINT=$(echo &quot;$line&quot; | awk '{print $6}')

    log_status &quot;  $MOUNT_POINT: ${DISK_USAGE}%&quot;

    if [ &quot;$DISK_USAGE&quot; -gt &quot;$THRESHOLD_DISK&quot; ]; then
        log_status &quot;  警告: $MOUNT_POINT 磁盘使用率超过${THRESHOLD_DISK}%!&quot;
    fi
done

# 检查系统负载
LOAD=$(uptime | awk -F'[a-z]:' '{print $2}' | awk '{print $1}' | tr -d ',')
CPU_CORES=$(nproc)
LOAD_PER_CORE=$(echo &quot;scale=2; $LOAD/$CPU_CORES&quot; | bc)

log_status &quot;系统负载: $LOAD (每核心: ${LOAD_PER_CORE})&quot;

if (( $(echo &quot;$LOAD_PER_CORE &gt; 1.0&quot; | bc -l) )); then
    log_status &quot;警告: 系统负载过高!&quot;
fi

# 检查运行时间
UPTIME=$(uptime -p)
log_status &quot;系统运行时间: $UPTIME&quot;

# 检查最近登录用户
log_status &quot;最近登录用户:&quot;
last | head -5 | awk '{print &quot;  &quot;$1&quot; 从 &quot;$3&quot; 于 &quot;$4&quot; &quot;$5&quot; &quot;$6&quot; &quot;$7&quot; &quot;$8}' &gt;&gt; &quot;$OUTPUT_FILE&quot;

log_status &quot;========== 系统状态检查结束 ==========&quot;

echo &quot;系统报告已保存至: $OUTPUT_FILE&quot;
</code></pre>
<h3 id="_6">备份脚本</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# [备份管理] 文件夹增量备份

# 配置
SOURCE_DIR=&quot;/path/to/source&quot;
BACKUP_DIR=&quot;/path/to/backups&quot;
MAX_BACKUPS=7
DATE_FORMAT=$(date +&quot;%Y%m%d_%H%M%S&quot;)
BACKUP_NAME=&quot;backup_${DATE_FORMAT}.tar.gz&quot;
LOG_FILE=&quot;/var/log/backup.log&quot;

# 创建日志文件
if [ ! -f &quot;$LOG_FILE&quot; ]; then
    touch &quot;$LOG_FILE&quot;
    chmod 644 &quot;$LOG_FILE&quot;
fi

# 日志函数
log() {
    echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] $1&quot; | tee -a &quot;$LOG_FILE&quot;
}

# 错误处理
handle_error() {
    log &quot;错误: $1&quot;
    exit 1
}

# 检查源目录
if [ ! -d &quot;$SOURCE_DIR&quot; ]; then
    handle_error &quot;源目录 $SOURCE_DIR 不存在！&quot;
fi

# 确保备份目录存在
if [ ! -d &quot;$BACKUP_DIR&quot; ]; then
    log &quot;创建备份目录 $BACKUP_DIR&quot;
    mkdir -p &quot;$BACKUP_DIR&quot; || handle_error &quot;无法创建备份目录&quot;
fi

# 执行备份
log &quot;开始备份 $SOURCE_DIR 到 $BACKUP_DIR/$BACKUP_NAME&quot;

tar -czf &quot;$BACKUP_DIR/$BACKUP_NAME&quot; -C &quot;$(dirname &quot;$SOURCE_DIR&quot;)&quot; &quot;$(basename &quot;$SOURCE_DIR&quot;)&quot; 2&gt;/dev/null

if [ $? -ne 0 ]; then
    handle_error &quot;备份创建失败&quot;
fi

# 计算备份大小
BACKUP_SIZE=$(du -h &quot;$BACKUP_DIR/$BACKUP_NAME&quot; | cut -f1)
log &quot;备份完成: $BACKUP_NAME (大小: $BACKUP_SIZE)&quot;

# 清理旧备份
BACKUP_COUNT=$(ls -1 &quot;$BACKUP_DIR&quot;/backup_*.tar.gz 2&gt;/dev/null | wc -l)

if [ &quot;$BACKUP_COUNT&quot; -gt &quot;$MAX_BACKUPS&quot; ]; then
    log &quot;清理旧备份，保留最新的 $MAX_BACKUPS 个备份&quot;
    ls -1t &quot;$BACKUP_DIR&quot;/backup_*.tar.gz | tail -n +$((MAX_BACKUPS+1)) | xargs rm -f
    log &quot;已清理 $((BACKUP_COUNT-MAX_BACKUPS)) 个旧备份&quot;
fi

# 显示备份统计
TOTAL_SIZE=$(du -sh &quot;$BACKUP_DIR&quot; | cut -f1)
log &quot;备份目录总大小: $TOTAL_SIZE&quot;
log &quot;备份保留策略: 保留最新 $MAX_BACKUPS 个备份&quot;

log &quot;备份操作成功完成&quot;
exit 0
</code></pre>
<h3 id="_7">日志分析脚本</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# [日志分析] Web服务器日志分析

# 配置
LOG_FILE=&quot;/var/log/nginx/access.log&quot;
REPORT_DIR=&quot;/tmp/log_analysis&quot;
TODAY=$(date +%Y%m%d)
REPORT_FILE=&quot;$REPORT_DIR/report_$TODAY.html&quot;

# 创建报告目录
mkdir -p &quot;$REPORT_DIR&quot;

# HTML报告头部
cat &gt; &quot;$REPORT_FILE&quot; &lt;&lt; EOL
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;服务器日志分析报告 - $TODAY&lt;/title&gt;
    &lt;style&gt;
        body { font-family: Arial, sans-serif; margin: 20px; }
        h1 { color: #333; }
        h2 { color: #0066cc; margin-top: 20px; }
        table { border-collapse: collapse; width: 100%; margin-top: 10px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        tr:nth-child(even) { background-color: #f9f9f9; }
        .chart { width: 100%; height: 300px; margin-top: 20px; }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;服务器日志分析报告 - $(date +%Y-%m-%d)&lt;/h1&gt;
EOL

echo &quot;正在分析日志 $LOG_FILE ...&quot;

# 总请求数
TOTAL_REQUESTS=$(wc -l &lt; &quot;$LOG_FILE&quot;)
echo &quot;&lt;h2&gt;概述&lt;/h2&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
echo &quot;&lt;p&gt;分析文件: $LOG_FILE&lt;/p&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
echo &quot;&lt;p&gt;总请求数: $TOTAL_REQUESTS&lt;/p&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;

# 访问量TOP 10 IP地址
echo &quot;&lt;h2&gt;访问量TOP 10 IP地址&lt;/h2&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
echo &quot;&lt;table&gt;&lt;tr&gt;&lt;th&gt;IP地址&lt;/th&gt;&lt;th&gt;请求数&lt;/th&gt;&lt;th&gt;百分比&lt;/th&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
awk '{print $1}' &quot;$LOG_FILE&quot; | sort | uniq -c | sort -nr | head -10 | while read -r count ip; do
    percent=$(echo &quot;scale=2; $count*100/$TOTAL_REQUESTS&quot; | bc)
    echo &quot;&lt;tr&gt;&lt;td&gt;$ip&lt;/td&gt;&lt;td&gt;$count&lt;/td&gt;&lt;td&gt;${percent}%&lt;/td&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
done
echo &quot;&lt;/table&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;

# HTTP状态码分布
echo &quot;&lt;h2&gt;HTTP状态码分布&lt;/h2&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
echo &quot;&lt;table&gt;&lt;tr&gt;&lt;th&gt;状态码&lt;/th&gt;&lt;th&gt;描述&lt;/th&gt;&lt;th&gt;数量&lt;/th&gt;&lt;th&gt;百分比&lt;/th&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
awk '{print $9}' &quot;$LOG_FILE&quot; | sort | uniq -c | sort -nr | while read -r count status; do
    percent=$(echo &quot;scale=2; $count*100/$TOTAL_REQUESTS&quot; | bc)
    description=&quot;&quot;
    case $status in
        200) description=&quot;成功&quot; ;;
        301) description=&quot;永久重定向&quot; ;;
        302) description=&quot;临时重定向&quot; ;;
        304) description=&quot;未修改&quot; ;;
        400) description=&quot;错误请求&quot; ;;
        403) description=&quot;禁止访问&quot; ;;
        404) description=&quot;未找到&quot; ;;
        500) description=&quot;服务器内部错误&quot; ;;
        502) description=&quot;网关错误&quot; ;;
        503) description=&quot;服务不可用&quot; ;;
        *) description=&quot;其他&quot; ;;
    esac
    echo &quot;&lt;tr&gt;&lt;td&gt;$status&lt;/td&gt;&lt;td&gt;$description&lt;/td&gt;&lt;td&gt;$count&lt;/td&gt;&lt;td&gt;${percent}%&lt;/td&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
done
echo &quot;&lt;/table&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;

# 访问量TOP 10的URL
echo &quot;&lt;h2&gt;访问量TOP 10的URL&lt;/h2&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
echo &quot;&lt;table&gt;&lt;tr&gt;&lt;th&gt;URL&lt;/th&gt;&lt;th&gt;请求数&lt;/th&gt;&lt;th&gt;百分比&lt;/th&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
awk '{print $7}' &quot;$LOG_FILE&quot; | sort | uniq -c | sort -nr | head -10 | while read -r count url; do
    percent=$(echo &quot;scale=2; $count*100/$TOTAL_REQUESTS&quot; | bc)
    echo &quot;&lt;tr&gt;&lt;td&gt;$url&lt;/td&gt;&lt;td&gt;$count&lt;/td&gt;&lt;td&gt;${percent}%&lt;/td&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
done
echo &quot;&lt;/table&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;

# 每小时请求量
echo &quot;&lt;h2&gt;每小时请求量分布&lt;/h2&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
echo &quot;&lt;table&gt;&lt;tr&gt;&lt;th&gt;小时&lt;/th&gt;&lt;th&gt;请求数&lt;/th&gt;&lt;th&gt;百分比&lt;/th&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
awk '{print substr($4, 14, 2)}' &quot;$LOG_FILE&quot; | sort | uniq -c | sort -k2n | while read -r count hour; do
    percent=$(echo &quot;scale=2; $count*100/$TOTAL_REQUESTS&quot; | bc)
    echo &quot;&lt;tr&gt;&lt;td&gt;$hour:00&lt;/td&gt;&lt;td&gt;$count&lt;/td&gt;&lt;td&gt;${percent}%&lt;/td&gt;&lt;/tr&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;
done
echo &quot;&lt;/table&gt;&quot; &gt;&gt; &quot;$REPORT_FILE&quot;

# HTML报告尾部
cat &gt;&gt; &quot;$REPORT_FILE&quot; &lt;&lt; EOL
&lt;/body&gt;
&lt;/html&gt;
EOL

echo &quot;分析报告已生成: $REPORT_FILE&quot;
</code></pre>
<h2 id="_8">实战应用场景</h2>
<h3 id="_9">自动化部署</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# [自动化部署] 前端项目自动化部署

# 配置
REPO_URL=&quot;git@github.com:username/project.git&quot;
PROJECT_DIR=&quot;/var/www/html/project&quot;
BACKUP_DIR=&quot;/var/www/backups&quot;
BRANCH=&quot;main&quot;
LOG_FILE=&quot;/var/log/deploy.log&quot;
NOTIFICATION_EMAIL=&quot;admin@example.com&quot;

# 日志函数
log() {
    echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] $1&quot; | tee -a &quot;$LOG_FILE&quot;
}

# 错误处理
handle_error() {
    log &quot;错误: $1&quot;
    # 发送告警
    curl -X POST &quot;https://api.example.com/notify&quot; \
         -d &quot;{'message': '部署失败: $1', 'level': 'error'}&quot;
    exit 1
}

log &quot;开始部署流程&quot;

# 检查目录是否存在
if [ ! -d &quot;$PROJECT_DIR&quot; ]; then
    log &quot;项目目录不存在，正在克隆仓库...&quot;
    git clone &quot;$REPO_URL&quot; -b &quot;$BRANCH&quot; &quot;$PROJECT_DIR&quot; || handle_error &quot;克隆仓库失败&quot;
    cd &quot;$PROJECT_DIR&quot; || handle_error &quot;无法进入项目目录&quot;
else
    log &quot;项目目录已存在，更新代码...&quot;
    cd &quot;$PROJECT_DIR&quot; || handle_error &quot;无法进入项目目录&quot;

    # 备份当前版本
    TIMESTAMP=$(date +&quot;%Y%m%d_%H%M%S&quot;)
    BACKUP_NAME=&quot;backup_${TIMESTAMP}.tar.gz&quot;
    log &quot;备份当前版本到 $BACKUP_DIR/$BACKUP_NAME&quot;

    mkdir -p &quot;$BACKUP_DIR&quot;
    tar -czf &quot;$BACKUP_DIR/$BACKUP_NAME&quot; . || handle_error &quot;备份失败&quot;

    # 拉取最新代码
    git fetch origin &quot;$BRANCH&quot; || handle_error &quot;获取最新代码失败&quot;
    git reset --hard &quot;origin/$BRANCH&quot; || handle_error &quot;重置到最新代码失败&quot;
fi

# 安装依赖
log &quot;安装项目依赖...&quot;
if [ -f &quot;package.json&quot; ]; then
    npm ci || handle_error &quot;NPM依赖安装失败&quot;
fi

# 构建项目
log &quot;构建项目...&quot;
if [ -f &quot;package.json&quot; ]; then
    npm run build || handle_error &quot;项目构建失败&quot;
fi

# 部署构建结果
if [ -d &quot;dist&quot; ]; then
    log &quot;部署构建结果...&quot;
    # 假设我们需要将构建结果复制到Web服务器目录
    cp -r dist/* /var/www/html/ || handle_error &quot;部署构建结果失败&quot;
fi

# 更新权限
log &quot;更新文件权限...&quot;
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

# 重启相关服务
log &quot;重启Web服务器...&quot;
systemctl restart nginx || handle_error &quot;重启Nginx失败&quot;

# 验证部署
log &quot;验证部署...&quot;
HTTP_CODE=$(curl -s -o /dev/null -w &quot;%{http_code}&quot; http://localhost)
if [ &quot;$HTTP_CODE&quot; != &quot;200&quot; ]; then
    handle_error &quot;部署验证失败，HTTP状态码: $HTTP_CODE&quot;
fi

log &quot;部署成功完成！&quot;
exit 0
</code></pre>
<h3 id="_10">批量用户管理</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# [用户管理] 批量创建和管理用户

# 配置
USER_FILE=&quot;users.csv&quot;  # 格式: username,uid,group,shell,comment
DEFAULT_PASSWORD=&quot;ChangeMe123!&quot;
PASSWORD_FILE=&quot;user_passwords.txt&quot;
LOG_FILE=&quot;user_management.log&quot;

# 日志函数
log() {
    echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] $1&quot; | tee -a &quot;$LOG_FILE&quot;
}

# 检查是否以root权限运行
if [ &quot;$(id -u)&quot; -ne 0 ]; then
    echo &quot;错误: 必须以root权限运行此脚本!&quot;
    exit 1
fi

# 检查用户文件是否存在
if [ ! -f &quot;$USER_FILE&quot; ]; then
    echo &quot;错误: 用户文件 $USER_FILE 不存在!&quot;
    exit 1
fi

# 创建密码文件
touch &quot;$PASSWORD_FILE&quot;
chmod 600 &quot;$PASSWORD_FILE&quot;
echo &quot;# 用户名:密码列表 - 创建于 $(date)&quot; &gt; &quot;$PASSWORD_FILE&quot;

# 读取CSV文件并创建用户
log &quot;开始批量创建用户...&quot;
IFS=&quot;,&quot;
while read -r username uid group shell comment; do
    # 跳过注释行和空行
    [[ &quot;$username&quot; =~ ^#.*$ || -z &quot;$username&quot; ]] &amp;&amp; continue

    log &quot;处理用户: $username&quot;

    # 检查用户是否已存在
    if id &quot;$username&quot; &amp;&gt;/dev/null; then
        log &quot;用户 $username 已存在，跳过创建&quot;
    else
        # 创建用户组（如果不存在）
        if ! getent group &quot;$group&quot; &gt;/dev/null; then
            log &quot;创建用户组: $group&quot;
            groupadd &quot;$group&quot; || log &quot;警告: 创建用户组 $group 失败&quot;
        fi

        # 创建用户
        useradd_cmd=&quot;useradd&quot;
        [ -n &quot;$uid&quot; ] &amp;&amp; useradd_cmd+=&quot; -u $uid&quot;
        [ -n &quot;$group&quot; ] &amp;&amp; useradd_cmd+=&quot; -g $group&quot;
        [ -n &quot;$shell&quot; ] &amp;&amp; useradd_cmd+=&quot; -s $shell&quot;
        [ -n &quot;$comment&quot; ] &amp;&amp; useradd_cmd+=&quot; -c \&quot;$comment\&quot;&quot;
        useradd_cmd+=&quot; $username&quot;

        log &quot;执行: $useradd_cmd&quot;
        eval &quot;$useradd_cmd&quot;

        if [ $? -eq 0 ]; then
            log &quot;用户 $username 创建成功&quot;

            # 生成随机密码或使用默认密码
            password=&quot;${DEFAULT_PASSWORD}&quot;

            # 设置用户密码
            echo &quot;$username:$password&quot; | chpasswd

            # 强制用户在首次登录时更改密码
            passwd -e &quot;$username&quot; &gt;/dev/null

            # 记录用户密码
            echo &quot;$username:$password&quot; &gt;&gt; &quot;$PASSWORD_FILE&quot;

            log &quot;用户 $username 密码设置完成，已强制首次登录更改密码&quot;
        else
            log &quot;错误: 创建用户 $username 失败&quot;
        fi
    fi
done &lt; &quot;$USER_FILE&quot;

log &quot;用户创建完成，密码信息已保存到 $PASSWORD_FILE&quot;
echo &quot;共创建用户数量: $(grep -v '^#' &quot;$PASSWORD_FILE&quot; | wc -l)&quot;

exit 0
</code></pre>
<h3 id="_11">服务健康检查</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# [服务监控] 关键服务健康检查与自动恢复

# 配置
CHECK_INTERVAL=300  # 检查间隔秒数
MAX_RESTART_ATTEMPTS=3  # 最大重启尝试次数
LOG_FILE=&quot;/var/log/service_monitor.log&quot;
NOTIFICATION_EMAIL=&quot;admin@example.com&quot;
SERVICES=(&quot;nginx&quot; &quot;mysql&quot; &quot;redis-server&quot; &quot;mongodb&quot; &quot;docker&quot;)
CRITICAL_SERVICES=(&quot;nginx&quot; &quot;mysql&quot;)
HTTP_ENDPOINTS=(
    &quot;http://localhost:80:200&quot;  # 格式: URL:期望状态码
    &quot;http://localhost:8080/api/health:200&quot;
)

# 日志函数
log() {
    echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] $1&quot; | tee -a &quot;$LOG_FILE&quot;
}

# 发送邮件通知
send_notification() {
    local subject=&quot;$1&quot;
    local message=&quot;$2&quot;
    echo &quot;$message&quot; | mail -s &quot;$subject&quot; &quot;$NOTIFICATION_EMAIL&quot;
    log &quot;已发送通知邮件: $subject&quot;
}

# 检查系统服务
check_system_service() {
    local service_name=&quot;$1&quot;
    local is_critical=&quot;$2&quot;
    local status

    log &quot;检查服务: $service_name&quot;
    if systemctl is-active &quot;$service_name&quot; &amp;&gt;/dev/null; then
        log &quot;服务 $service_name 正在运行&quot;
        return 0
    else
        log &quot;警告: 服务 $service_name 未运行&quot;

        # 尝试重启服务
        local attempt=1
        while [ $attempt -le $MAX_RESTART_ATTEMPTS ]; do
            log &quot;尝试重启服务 $service_name (尝试 $attempt/$MAX_RESTART_ATTEMPTS)&quot;
            systemctl restart &quot;$service_name&quot;
            sleep 10

            if systemctl is-active &quot;$service_name&quot; &amp;&gt;/dev/null; then
                log &quot;服务 $service_name 已成功重启&quot;
                send_notification &quot;服务恢复通知&quot; &quot;服务 $service_name 已在第 $attempt 次尝试后成功重启。&quot;
                return 0
            fi

            attempt=$((attempt + 1))
        done

        # 如果是关键服务且重启失败，发送紧急通知
        if [ &quot;$is_critical&quot; = &quot;yes&quot; ]; then
            send_notification &quot;紧急: 关键服务宕机&quot; &quot;服务 $service_name 在尝试 $MAX_RESTART_ATTEMPTS 次后仍然无法重启。请立即处理！&quot;
        else
            send_notification &quot;服务宕机通知&quot; &quot;服务 $service_name 在尝试 $MAX_RESTART_ATTEMPTS 次后仍然无法重启。&quot;
        fi
        return 1
    fi
}

# HTTP端点健康检查
check_http_endpoint() {
    local endpoint=&quot;$1&quot;
    local url=&quot;${endpoint%:*}&quot;
    local expected_status=&quot;${endpoint##*:}&quot;

    log &quot;检查HTTP端点: $url (期望状态码: $expected_status)&quot;

    local http_status
    http_status=$(curl -s -o /dev/null -w &quot;%{http_code}&quot; &quot;$url&quot;)

    if [ &quot;$http_status&quot; = &quot;$expected_status&quot; ]; then
        log &quot;HTTP端点 $url 状态正常 ($http_status)&quot;
        return 0
    else
        log &quot;警告: HTTP端点 $url 状态异常 (得到: $http_status, 期望: $expected_status)&quot;
        send_notification &quot;HTTP服务异常&quot; &quot;HTTP端点 $url 状态码异常: 期望 $expected_status，实际 $http_status。&quot;
        return 1
    fi
}

# 检查端口是否开放
check_port() {
    local port=&quot;$1&quot;
    local service_name=&quot;$2&quot;

    log &quot;检查端口 $port ($service_name)&quot;

    if netstat -tuln | grep -q &quot;:$port &quot;; then
        log &quot;端口 $port ($service_name) 已开放&quot;
        return 0
    else
        log &quot;警告: 端口 $port ($service_name) 未开放&quot;
        send_notification &quot;端口检查失败&quot; &quot;服务 $service_name 的端口 $port 未开放。&quot;
        return 1
    fi
}

# 主循环
log &quot;服务监控脚本启动&quot;

while true; do
    log &quot;开始检查周期...&quot;

    # 检查系统服务
    for service in &quot;${SERVICES[@]}&quot;; do
        if [[ &quot; ${CRITICAL_SERVICES[*]} &quot; == *&quot; $service &quot;* ]]; then
            check_system_service &quot;$service&quot; &quot;yes&quot;
        else
            check_system_service &quot;$service&quot; &quot;no&quot;
        fi
    done

    # 检查HTTP端点
    for endpoint in &quot;${HTTP_ENDPOINTS[@]}&quot;; do
        check_http_endpoint &quot;$endpoint&quot;
    done

    # 检查关键端口
    check_port &quot;80&quot; &quot;Web服务器&quot;
    check_port &quot;3306&quot; &quot;MySQL&quot;
    check_port &quot;6379&quot; &quot;Redis&quot;

    log &quot;检查周期完成，等待 $CHECK_INTERVAL 秒后进行下一次检查...&quot;
    sleep &quot;$CHECK_INTERVAL&quot;
done
</code></pre>
<h2 id="_12">调试与故障排除技巧</h2>
<h3 id="_13">常用调试技巧</h3>
<ol>
<li><strong>添加调试标志</strong>：</li>
</ol>
<pre><code class="language-bash">#!/bin/bash
DEBUG=true  # 设置为false关闭调试输出

debug() {
    if [ &quot;$DEBUG&quot; = true ]; then
        echo &quot;[DEBUG] $1&quot;
    fi
}

debug &quot;这是一条调试信息&quot;
</code></pre>
<ol>
<li><strong>跟踪脚本执行</strong>：</li>
</ol>
<pre><code class="language-bash"># 在脚本顶部添加以启用跟踪
set -x  # 启用跟踪
command1
command2
set +x  # 关闭跟踪
</code></pre>
<ol>
<li><strong>单步执行</strong>：</li>
</ol>
<pre><code class="language-bash"># 使用trap调试
trap 'echo &quot;按Enter继续...&quot;; read' DEBUG
</code></pre>
<ol>
<li><strong>查看变量值</strong>：</li>
</ol>
<pre><code class="language-bash"># 显示所有已定义的变量
set | grep VAR_PREFIX

# 打印变量类型和值
declare -p VARIABLE_NAME
</code></pre>
<h3 id="_14">常见陷阱与解决方案</h3>
<ol>
<li><strong>空变量导致的问题</strong>：</li>
</ol>
<pre><code class="language-bash"># 不安全的用法
rm -rf $DIR/logs

# 安全的用法
if [ -n &quot;$DIR&quot; ] &amp;&amp; [ -d &quot;$DIR/logs&quot; ]; then
    rm -rf &quot;$DIR/logs&quot;
fi
</code></pre>
<ol>
<li><strong>忘记引用变量</strong>：</li>
</ol>
<pre><code class="language-bash"># 不安全（文件名含空格会出问题）
for file in $(ls *.txt); do
    cp $file /backup/

# 安全的方式
for file in *.txt; do
    cp &quot;$file&quot; /backup/
done
</code></pre>
<ol>
<li><strong>错误的退出状态检查</strong>：</li>
</ol>
<pre><code class="language-bash"># 不好的方式
command
if [ $? -ne 0 ]; then
    # 处理错误
fi

# 更好的方式
if ! command; then
    # 处理错误
fi
</code></pre>
<h3 id="_15">日志记录最佳实践</h3>
<pre><code class="language-bash">#!/bin/bash
# 高级日志记录

# 日志级别
LOG_LEVEL_ERROR=0
LOG_LEVEL_WARNING=1
LOG_LEVEL_INFO=2
LOG_LEVEL_DEBUG=3

# 设置当前日志级别
CURRENT_LOG_LEVEL=$LOG_LEVEL_INFO

# 日志文件
LOG_FILE=&quot;/var/log/script.log&quot;
MAX_LOG_SIZE_MB=10

# 日志轮转函数
rotate_log() {
    if [ -f &quot;$LOG_FILE&quot; ]; then
        local file_size=$(du -m &quot;$LOG_FILE&quot; | cut -f1)
        if [ &quot;$file_size&quot; -ge &quot;$MAX_LOG_SIZE_MB&quot; ]; then
            mv &quot;$LOG_FILE&quot; &quot;${LOG_FILE}.1&quot;
            touch &quot;$LOG_FILE&quot;
            chmod 644 &quot;$LOG_FILE&quot;
            echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] 日志文件已轮转&quot; &gt;&gt; &quot;$LOG_FILE&quot;
        fi
    fi
}

# 日志函数
log() {
    local level=$1
    local level_name=$2
    local message=$3

    if [ &quot;$level&quot; -le &quot;$CURRENT_LOG_LEVEL&quot; ]; then
        local log_entry=&quot;[$(date '+%Y-%m-%d %H:%M:%S')] [$level_name] $message&quot;

        # 打印到控制台
        echo &quot;$log_entry&quot;

        # 写入日志文件
        echo &quot;$log_entry&quot; &gt;&gt; &quot;$LOG_FILE&quot;

        # 检查是否需要轮转日志
        rotate_log
    fi
}

# 封装不同日志级别的函数
log_error() {
    log $LOG_LEVEL_ERROR &quot;ERROR&quot; &quot;$1&quot;
}

log_warning() {
    log $LOG_LEVEL_WARNING &quot;WARNING&quot; &quot;$1&quot;
}

log_info() {
    log $LOG_LEVEL_INFO &quot;INFO&quot; &quot;$1&quot;
}

log_debug() {
    log $LOG_LEVEL_DEBUG &quot;DEBUG&quot; &quot;$1&quot;
}

# 示例使用
log_info &quot;脚本已启动&quot;
log_debug &quot;这是一条调试信息&quot;
log_warning &quot;这是一条警告信息&quot;
log_error &quot;这是一条错误信息&quot;
</code></pre>
<h2 id="_16">进阶脚本编程</h2>
<h3 id="_17">函数库与模块化</h3>
<p>创建可重用的函数库：</p>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# 文件名: common_functions.sh
# 描述: 常用函数库

# 日志函数
log() {
    local timestamp=$(date &quot;+%Y-%m-%d %H:%M:%S&quot;)
    echo &quot;[$timestamp] $1&quot;
}

# 检查命令是否存在
command_exists() {
    command -v &quot;$1&quot; &gt;/dev/null 2&gt;&amp;1
}

# 获取OS类型
get_os_type() {
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        echo &quot;$ID&quot;
    elif [ -f /etc/redhat-release ]; then
        echo &quot;rhel&quot;
    else
        echo &quot;unknown&quot;
    fi
}

# 检查是否为root用户
is_root() {
    [ &quot;$(id -u)&quot; -eq 0 ]
}

# 获取IP地址
get_ip_address() {
    local interface=&quot;${1:-eth0}&quot;
    ip -4 addr show &quot;$interface&quot; | grep -oP &quot;(?&lt;=inet ).*(?=/)&quot;
}

# 安全地创建目录
safe_mkdir() {
    if [ ! -d &quot;$1&quot; ]; then
        mkdir -p &quot;$1&quot; || return 1
    fi
    return 0
}
</code></pre>
<p>使用函数库：</p>
<pre><code class="language-bash">#!/bin/bash
# 引入函数库
source ./common_functions.sh

# 使用库中的函数
log &quot;开始执行任务&quot;

if ! command_exists &quot;docker&quot;; then
    log &quot;错误: Docker未安装&quot;
    exit 1
fi

if ! is_root; then
    log &quot;错误: 此脚本需要root权限运行&quot;
    exit 1
fi

OS=$(get_os_type)
log &quot;操作系统: $OS&quot;

IP=$(get_ip_address)
log &quot;IP地址: $IP&quot;

if safe_mkdir &quot;/var/log/myapp&quot;; then
    log &quot;成功创建日志目录&quot;
else
    log &quot;创建日志目录失败&quot;
fi
</code></pre>
<h3 id="_18">信号处理与优雅退出</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# 带信号处理的脚本示例

# 临时文件
TEMP_FILE=&quot;/tmp/script_temp_$$.txt&quot;
PID_FILE=&quot;/var/run/script.pid&quot;

# 清理函数
cleanup() {
    echo &quot;捕获信号，正在清理...&quot;
    [ -f &quot;$TEMP_FILE&quot; ] &amp;&amp; rm -f &quot;$TEMP_FILE&quot;
    [ -f &quot;$PID_FILE&quot; ] &amp;&amp; rm -f &quot;$PID_FILE&quot;
    echo &quot;清理完成，退出脚本&quot;
    exit 0
}

# 注册信号处理器
trap 'cleanup' SIGINT SIGTERM EXIT

# 创建PID文件
echo $$ &gt; &quot;$PID_FILE&quot;

echo &quot;脚本已启动，PID: $$&quot;
echo &quot;按Ctrl+C退出&quot;

# 模拟长时间运行的脚本
while true; do
    echo &quot;$(date): 正在处理...&quot; &gt;&gt; &quot;$TEMP_FILE&quot;
    echo &quot;正在运行中...&quot;
    sleep 5
done
</code></pre>
<h3 id="_19">并发处理</h3>
<pre><code class="language-bash">#!/bin/bash
# @author Loganli
# 并发处理示例

# 配置
MAX_PROCESSES=4
WORK_DIR=&quot;/path/to/work&quot;
OUTPUT_DIR=&quot;/path/to/output&quot;
LOG_FILE=&quot;parallel_process.log&quot;

# 确保目录存在
mkdir -p &quot;$OUTPUT_DIR&quot;

# 日志函数
log() {
    echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] $1&quot; | tee -a &quot;$LOG_FILE&quot;
}

# 处理单个文件的函数
process_file() {
    local file=&quot;$1&quot;
    local filename=$(basename &quot;$file&quot;)

    log &quot;开始处理文件: $filename (PID: $$)&quot;

    # 这里是实际的处理逻辑
    sleep 2  # 模拟处理时间

    # 假设我们处理图片
    if [[ &quot;$file&quot; == *.jpg || &quot;$file&quot; == *.png ]]; then
        # 使用convert(ImageMagick)调整图片大小
        if command -v convert &amp;&gt;/dev/null; then
            convert &quot;$file&quot; -resize &quot;800x600&gt;&quot; &quot;$OUTPUT_DIR/$filename&quot;
            log &quot;文件 $filename 处理完成&quot;
        else
            log &quot;错误: 未找到convert命令&quot;
            return 1
        fi
    else
        # 简单地复制其他类型的文件
        cp &quot;$file&quot; &quot;$OUTPUT_DIR/&quot;
        log &quot;文件 $filename 已复制&quot;
    fi

    return 0
}

# 导出函数以便子shell可以使用
export -f process_file
export -f log
export OUTPUT_DIR
export LOG_FILE

log &quot;开始并行处理任务，最大并发数: $MAX_PROCESSES&quot;

# 查找并并行处理文件
find &quot;$WORK_DIR&quot; -type f | xargs -P &quot;$MAX_PROCESSES&quot; -I{} bash -c 'process_file &quot;{}&quot;'

# 或者使用GNU并行工具
# find &quot;$WORK_DIR&quot; -type f | parallel -j &quot;$MAX_PROCESSES&quot; process_file

log &quot;所有文件处理完成&quot;
</code></pre>
<h3 id="shell_1">Shell性能优化技巧</h3>
<p>提高Shell脚本性能的几种方法：</p>
<ol>
<li><strong>减少进程创建</strong>：</li>
</ol>
<pre><code class="language-bash"># 低效方式（每行创建一个进程）
for i in $(seq 1 100); do
    echo &quot;$i&quot;
done | grep &quot;5&quot;

# 高效方式（使用内部功能）
for ((i=1; i&lt;=100; i++)); do
    [[ &quot;$i&quot; =~ 5 ]] &amp;&amp; echo &quot;$i&quot;
done
</code></pre>
<ol>
<li><strong>使用内置功能</strong>：</li>
</ol>
<pre><code class="language-bash"># 低效方式
if echo &quot;$string&quot; | grep -q &quot;pattern&quot;; then
    # ...
fi

# 高效方式（使用bash内置功能）
if [[ &quot;$string&quot; =~ pattern ]]; then
    # ...
fi
</code></pre>
<ol>
<li><strong>降低I/O操作</strong>：</li>
</ol>
<pre><code class="language-bash"># 低效（多次写入文件）
for i in {1..100}; do
    echo &quot;$i&quot; &gt;&gt; output.txt
done

# 高效（一次写入）
{
    for i in {1..100}; do
        echo &quot;$i&quot;
    done
} &gt; output.txt
</code></pre>
<ol>
<li><strong>避免不必要的命令执行</strong>：</li>
</ol>
<pre><code class="language-bash"># 低效
count=$(ls -1 | wc -l)

# 高效
count=$(find . -maxdepth 1 -type f | wc -l)

# 更高效（纯bash，无子进程）
shopt -s nullglob
files=(*)
count=${#files[@]}
</code></pre>
<ol>
<li><strong>使用适当的工具</strong>：</li>
</ol>
<pre><code class="language-bash"># 文本处理选择正确的工具：
# - 简单替换用sed
# - 提取信息用grep
# - 复杂数据处理用awk
# - 极其复杂的处理考虑使用Python等更高级语言
</code></pre>
<p>这些实践将帮助你创建更加高效、健壮的Shell脚本。记住，好的脚本不仅能完成任务，还要考虑错误处理、安全性和性能。</p>












                
              </article>
            </div>
          
          
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
        </div>
        
      </main>
      
        <footer class="md-footer">
  
  <div class="md-footer-meta md-typeset">
    <div class="md-footer-meta__inner md-grid">
      <div class="md-copyright">
  
  
    Made with
    <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
      Material for MkDocs
    </a>
  
</div>
      
        <div class="md-social">
  
    
    
    
    
      
      
    
    <a href="https://git.opsx.vip/docs/PythonFullStackGuide.git" target="_blank" rel="noopener" title="git.opsx.vip" class="md-social__link">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
    </a>
  
    
    
    
    
    <a href="mailto:admin@attacker.club" target="_blank" rel="noopener" title="" class="md-social__link">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4l217.6 163.2c11.4 8.5 27 8.5 38.4 0l217.6-163.2c12.1-9.1 19.2-23.3 19.2-38.4 0-26.5-21.5-48-48-48zM0 176v208c0 35.3 28.7 64 64 64h384c35.3 0 64-28.7 64-64V176L294.4 339.2a63.9 63.9 0 0 1-76.8 0z"/></svg>
    </a>
  
</div>
      
    </div>
  </div>
</footer>
      
    </div>
    <div class="md-dialog" data-md-component="dialog">
      <div class="md-dialog__inner md-typeset"></div>
    </div>
    
    
    <script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../../assets/javascripts/workers/search.f8cc74c7.min.js", "translations": {"clipboard.copied": "\u5df2\u590d\u5236", "clipboard.copy": "\u590d\u5236", "search.result.more.one": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.more.other": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 # \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.none": "\u6ca1\u6709\u627e\u5230\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.one": "\u627e\u5230 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.other": "# \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.placeholder": "\u952e\u5165\u4ee5\u5f00\u59cb\u641c\u7d22", "search.result.term.missing": "\u7f3a\u5c11", "select.version": "\u9009\u62e9\u5f53\u524d\u7248\u672c"}}</script>
    
    
      <script src="../../assets/javascripts/bundle.60a45f97.min.js"></script>
      
        <script src="../../js/prism.js"></script>
      
    
  </body>
</html>